using System;
using System.Collections;
using System.Web.UI;
using PHSRAG.Insight21.Common.Pages;
using PHSRAG.Insight21.Context;
using PHSRAG.Insight21.FormsManagement;
using PHSRAG.Insight21.FormsManagement.Serialization;
using PHSRAG.Insight21.Policy;
using PHSRAG.Insight21.ScriptEngine;
using PHSRAG.Utility;
using BO = PHSRAG.Insight21.BusinessObjects;
using HeaderControl = PHSRAG.Insight21.InsightWebControls.Header;
using ScriptReference = PHSRAG.Insight21.ScriptEngine.ScriptReference;

namespace PHSRAG.Insight21.Humans
{
    public partial class NewProtocolApplication : BasePage
    {
        #region Private instance variables.

        private ICachePolicy cachePolicy;
        private Protocol newProtocol;
        private Hashtable pageCache;
        private ICachePolicy pageCachePolicy;

        #endregion

        #region constants

        private const string loadErrorText = "Error loading the page.";
        private const string PageCacheKey = "newProtocolApplicationPage__C81DA451-E37D-485b-9160-5FAB062DF42A";
        private const string saveErrorText = "Error occurred creating protocol.";

        #endregion

        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                pageCache = pageCachePolicy.GetCachedObject(PageCacheKey) as Hashtable ?? new Hashtable();

                breadCrumb.Add(
                    "New Protocol Application",
                    Settings.GetKeyValue("SubModuleNavigation.Humans.NewProtocolAppURL", ""),
                    Settings.GetKeyValue("BreadCrumb.DetailPageLevel", 2));

                annunciator.Message = string.Empty;

                if (!IsPostBack)
                {
                    // default to New Application.
                    string protocolType;

                    Hashtable incomingPageHash =
                        cachePolicy.GetCachedObject(Keys.IncomingDataKey) as Hashtable;
                    if (incomingPageHash != null)
                    {
                        protocolType = (string) (incomingPageHash[Keys.NewProtocolAppTypeKey]);
                    }
                    else
                    {
                        protocolType = Constants.NewProtocolType.NewApplication;
                    }

                    QuestionnaireVersion newProtocolQV = null;

                    switch (protocolType)
                    {
                        case Constants.NewProtocolType.NewApplication:
                            newProtocolQV = Questionnaire.GetActiveVersionByCategoryAndType(
                                cachePolicy,
                                FormsManagement.Constants.InitialApplicationCategory.InitialQuestionnaire,
                                FormsManagement.Constants.QuestionnaireType.InitialApplication);
                            break;
                        case Constants.NewProtocolType.EmergencyApp:
                            newProtocolQV = Questionnaire.GetActiveVersionByCategoryAndType(
                                cachePolicy,
                                FormsManagement.Constants.EmergencyUseCategory.InitialQuestionnaire,
                                FormsManagement.Constants.QuestionnaireType.EmergencyUser);
                            break;
                        case Constants.ModuleType.Animals:
                            // There is only one Animals protocol type upon initial survey
                            newProtocolQV = Questionnaire.GetActiveVersionByCategoryAndType(
                                cachePolicy,
                                FormsManagement.Constants.AnimalsFormCatgory.InitialApplication,
                                FormsManagement.Constants.QuestionnaireType.Animals);
                            versionPlaceholder.Visible = false;
                            break;
                    }

                    if (newProtocolQV == null)
                    {
                        annunciator.Message = "No Initial Review Questionnaire exists. Please contact the Insight Help Desk.";
                        // hide the controls since there are no questions to answer.
                        questionnaireViewer.ContinueLoading = false;
                        questionnaireViewer.Visible = false;
                        titleLabel.Visible = false;
                        versionLabel.Visible = false;
                        protocolTitle.Visible = false;
                        protocolVersion.Visible = false;
                        saveProtocol.Visible = false;
                    }
                    else
                    {
                        // pass this to teh Viewer control
                        questionnaireViewer.LoadQuestionnaire(newProtocolQV, null);

                        // cache the QV
                        newProtocolQV.Cache();
                    }
                    if (header.ModuleName.ToLower() == "animals")
                    {
                        instructions1.Text = "Please answer the following questions in order to " +
                            "customize your animal research submission. The answers to these " +
                                "questions will determine what information is required for review by " +
                                    "the Subcommittee on Research Animal Care.";
                    }
                }
            }
            catch (Exception ex)
            {
                annunciator.Title = loadErrorText;
                annunciator.Message = ex.Message;
            }
        }

        private bool ValidateProtocol()
        {
            if (protocolTitle.Text.Trim() == string.Empty)
            {
                // Keep the questions expanded
                questionnaireViewer.Refresh();
                annunciator.Title = InsightUtilities.Constants.Annunciator.Title;
                annunciator.Message = "Full title of the study is empty.";
                saveProtocol.Enabled = true;
                return false;
            }
            if (header.ModuleName.ToLower() == "humans")
            {
                // On a humans protocol, at least one of the questions in the configuration
                // must be answered with a yes.
                FormItem item = questionnaireViewer.Form.FormItems[0] as FormItem;
                bool oneYes = (item.Answers[0] as FormAnswer).Answer.StartsWith("Y");

                for (int i = 0; i < Int32.Parse(Utility.Settings.GetKeyValue("HumanNonIntervQuestionsIndex", "6")); i++)
                {
                    if (!oneYes && item.FormItems.Count > 0)
                    {
                        item = item.FormItems[0] as FormItem;
                        oneYes = (item.Answers[0] as FormAnswer).Answer.StartsWith("Y");
                    }
                }

                if (!oneYes)
                {
                    // Need to remove the no answers, because when you set one to yes
                    // it isn't updated in the current design.
                    item = questionnaireViewer.Form.FormItems[0] as FormItem;
                    item.RemoveAnswer();
                    for (int i = 0; i < 5; i++)
                    {
                        item = item.FormItems[0] as FormItem;
                        item.RemoveAnswer();
                    }
                    // update the questionnaire UI
                    questionnaireViewer.Refresh();
                    annunciator.Title = InsightUtilities.Constants.Annunciator.Title;
                    annunciator.Message = "You must answer yes to at least one of the questions in the configuration wizard.";
                    saveProtocol.Enabled = true;
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// Handler for the event raised when the Save button is clicked.
        /// </summary>
        /// <param name="sender">The control which raised the event.</param>
        /// <param name="e">Arguments assocoiated with the event</param>
        private void OnSaveProtocol(object sender, ImageClickEventArgs e)
        {
            try
            {
                if (!ValidateProtocol())
                {
                    return;
                }

                newProtocol = new Protocol(cachePolicy);
                // set the type.
                Hashtable incomingPageHash =
                    cachePolicy.GetCachedObject(Keys.IncomingDataKey) as Hashtable;
                if (incomingPageHash != null)
                {
                    newProtocol.ProtocolTypeCode = (string) (incomingPageHash[Keys.NewProtocolAppTypeKey]);
                }
                else
                {
                    newProtocol.ProtocolTypeCode = Constants.NewProtocolType.NewApplication;
                }

                newProtocol.ModuleType =
                    (header.ModuleName.ToLower() == "animals") ? Constants.ModuleType.Animals : Constants.ModuleType.Humans;

                newProtocol.OverallStatusId = (int) Constants.ProtocolOverallStatus.WorkInProgress;
                newProtocol.OverallStatus = Constants.ProtocolOverallStatusText.WorkInProgress;

                Application newApp = (Application) newProtocol.GetNewProcess(newProtocol.ModuleType == Constants.ModuleType.Animals ? ProtocolProcessType.AnimalsApplication : ProtocolProcessType.Application, cachePolicy, DataAccess.GetConnectionString());

                UserContext userContext = cachePolicy.GetCachedObject(UserContext.CacheKey) as UserContext;
                newApp.SubmitterId = userContext.DomainUserId;
                newApp.LastModifiedByUserId = userContext.DomainUserId;
                newProtocol.CreatorId = userContext.DomainUserId;

                // set the submitter to the logged in user
                newApp.SubmitterId = userContext.DomainUserId;

                // create a new ProtocolVersion since it's the first one.
                ProtocolVersion currentVersion = newApp.AddNewVersion(cachePolicy);
                currentVersion.Version = 1;

                // set the Protocol strings from teh fields on the screen.
                newProtocol.Title = protocolTitle.Text;
                newProtocol.Version = protocolVersion.Text;

                // grab the list of questions from the Forms control, and save them as appropriate
                QuestionnaireAnswer initialRevAnswers = new QuestionnaireAnswer(cachePolicy);
                initialRevAnswers.LastModifiedByAdmPersonId = userContext.PersonId;


                if (!questionnaireViewer.ValidateRequiredQuestions("All the questions have to be answered before the new protocol can be saved."))
                {
                    saveProtocol.Enabled = true;
                    return;
                }
                if (!questionnaireViewer.VerifyTextboxAnswers())
                {
                    return;
                }
                questionnaireViewer.SaveQuestionnaire(initialRevAnswers);

                // get teh cached QV to set the appropriate ID.
                QuestionnaireVersion initialReviewQV = new QuestionnaireVersion(cachePolicy);

                initialReviewQV = (QuestionnaireVersion) cachePolicy.GetCachedObject(initialReviewQV.CacheKey());

                initialRevAnswers.Name = "InitialReview";
                initialRevAnswers.QuestionnaireVersionId = initialReviewQV.Id;

                currentVersion.QuestionnaireAnswers.Add(initialRevAnswers);

                // call Save on the Protocol
                newProtocol.Save(DataAccess.GetConnectionString());

                // now get the appropriate requirement Script from teh Questionnaire Version and run it, 
                // passing in the Protocol and QuestioinnaireAnswers as Intrinsics.
                Script requirementScript =
                    (Script) initialReviewQV.Scripts[FormsManagement.Constants.ScriptType.Requirement];

                if (requirementScript != null)
                {
                    using (ScriptEngineHost scriptHost =
                        new ScriptEngineHost("RequirementScript://Scripting/", "RequirementScript", true))
                    {
                        ArrayList refs = ScriptReference.GetAllScriptReferences(DataAccess.GetConnectionString());

                        for (int i = 0; i < refs.Count; ++i)
                        {
                            ScriptReference reference = (ScriptReference) refs[i];
                            scriptHost.AddDLLReference(reference.Path);
                        }

                        // add this protocol as an intrinsic.
                        scriptHost.AddIntrinsicObject("theProtocol", newProtocol);

                        // add the connection string
                        scriptHost.AddIntrinsicObject("connectionString", DataAccess.GetConnectionString());

                        // add the Process
                        scriptHost.AddIntrinsicObject("applicationProtProcess", newApp);

                        // add the version
                        scriptHost.AddIntrinsicObject("currentProtVersion", currentVersion);

                        // add the caching policy
                        scriptHost.AddIntrinsicObject("cachePolicy", cachePolicy);

                        if (scriptHost.Compile(requirementScript))
                        {
                            scriptHost.RunScript(requirementScript, "RequirementScript.Script", "Main");
                        }
                    }
                }

                // cache some things
                Hashtable outgoingData = new Hashtable();
                outgoingData.Add(Keys.ProtocolIdKey, newProtocol.Id);
                outgoingData.Add(Keys.ProtocolProcessIdKey, newApp.Id);
                outgoingData.Add(Keys.ProtocolVersionNumberKey, currentVersion.Version);
                outgoingData.Add(Keys.ProtocolVersionIdKey, currentVersion.Id);
                outgoingData.Add(Keys.ProtocolAccessKey, newProtocol.ManagePermission);
                pageCachePolicy.Cache(Keys.IncomingDataKey, outgoingData);

                // cache the objects we'll need in the later pages
                newProtocol.Cache();
                newApp.Cache();
                currentVersion.Cache();

                // now that it's saved, redirect the user to the ProtocolProcessOverview page.
                Page.Response.Redirect(
                    Settings.GetKeyValue("SubModuleNavigation.Humans.ProtocolProcessOverviewURL", ""), false);
            }
            catch (Exception ex)
            {
                annunciator.Title = "Error occurred creating protocol.";
                annunciator.Message = ex.Message;
                saveProtocol.Visible = false;
            }
        }

        #region Web Form Designer generated code

        /// <summary>
        /// Handler for the event raised when the page is being initialized.
        /// Retrieve the cache policy in force.
        /// </summary>
        /// <param name="e">Arguments assocoiated with the event</param>
        protected override void OnInit(EventArgs e)
        {
            //
            // CODEGEN: This call is required by the ASP.NET Web Form Designer.
            //
            InitializeComponent();
            base.OnInit(e);

            cachePolicy = (Policy.ICachePolicy) Session[Policy.Names.CachePolicyKey];
            pageCachePolicy = (Policy.ICachePolicy) Session[Policy.Names.PageCachePolicyKey];
            saveProtocol.Attributes["onclick"] = "DisableSave();";
        }

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.saveProtocol.Click += new ImageClickEventHandler(OnSaveProtocol);
        }

        #endregion
    }
}